/*
 * This file Copyright (c) 2015. Walle.
 * (http://www.wallellen.com). All rights reserved.
 *
 *
 * This file is dual-licensed under both the
 * Walle Agreement (WA) and the GNU General Public License.
 * You may elect to use one or the other of these licenses.
 *
 * This file is distributed in the hope that it will be
 * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
 * implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
 * Redistribution, except as permitted by whichever of the GPL
 * or WA you select, is prohibited.
 *
 * 1. For the GPL license (GPL), you can redistribute and/or
 * modify this file under the terms of the GNU General
 * Public License, Version 3, as published by the Free Software
 * Foundation.  You should have received a copy of the GNU
 * General Public License, Version 3 along with this program;
 * if not, write to the Free Software Foundation, Inc., 51
 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 2. For the Walle Agreement (WA), this file
 * and the accompanying materials are made available under the
 * terms of the WA which accompanies this distribution, and
 * is available at http://www.wallellen.com/agreement.html
 *
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 */

package com.wallellen.knowledge.doc.server.impl;

import com.wallellen.core.sql.result.DataResult;
import com.wallellen.core.sql.result.ResultsHandle;
import com.wallellen.knowledge.doc.dao.DocDaoInter;
import com.wallellen.knowledge.doc.domain.Doc;
import com.wallellen.knowledge.doc.domain.ex.DocBrief;
import com.wallellen.knowledge.doc.domain.ex.DocEntire;
import com.wallellen.knowledge.doc.server.DocIndexInter;
import com.wallellen.knowledge.doc.server.DocOperateRightInter;
import com.wallellen.knowledge.doc.server.DocgroupManagerInter;
import com.wallellen.knowledge.doc.util.HtmlUtils;
import com.wallellen.knowledge.doc.util.LuceneDocUtil;
import com.wallellen.lucene.LuceneFace;
import com.wallellen.lucene.server.DocQueryImpl;
import com.wallellen.lucene.server.DocQueryInter;
import com.wallellen.parameter.ParamService;
import com.wallellen.util.web.WebHotCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Service
public class DocIndexManagerImpl implements DocIndexInter {
    @Resource
    private DocDaoInter farmDocDao;

    @Resource
    private DocOperateRightInter farmDocOperate;
    @Resource
    private DocgroupManagerInter farmDocgroupManagerImpl;
    private final static Logger log = LoggerFactory.getLogger(DocIndexManagerImpl.class);

    @Override
    @Transactional
    public List<DocBrief> getRelationDocs(String docid, int num) {
        Doc doc = farmDocDao.getEntity(docid);
        List<File> file = new ArrayList<>();
        file.add(LuceneFace.inctance()
                .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_FILE")));
        file.add(LuceneFace.inctance()
                .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_KNOW")));
        file.add(LuceneFace.inctance()
                .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_SITE")));
        DocQueryInter query = DocQueryImpl.getInstance(file);
        String iql = null;
        if (iql == null) {
            iql = "WHERE(TITLE,TEXT=" + HtmlUtils.HtmlRemoveTag(doc.getTitle().trim()).replaceAll(":", "") + ")";
        }
        try {
            DataResult result = query.queryByMultiIndex(iql, 1, num).getDataResult();
            result.runHandle((new ResultsHandle() {
                @Override
                public void handle(Map<String, Object> row) {
                    row.put("DOCID", row.get("ID"));
                }
            }));
            return result.getObjectList(DocBrief.class);
        } catch (Exception e) {
            log.error(e.toString());
            return Collections.EMPTY_LIST;
        }
    }

    @Override
    public DataResult search(String word, String userid, Integer pagenum) throws Exception {
        // TITLE,PUBTIME,VISITNUM,TYPENAME,AUTHOR,TAGKEY,DOCDESCRIBE,TEXT
        List<File> files = new ArrayList<File>();
        if (userid != null) {
            DataResult groups = farmDocgroupManagerImpl.getGroupsByUser(userid, 1000, 1);
            for (Map<String, Object> node : groups.getResultList()) {
                File file = LuceneFace.inctance().getIndexPathFile("GROUP" + (String) node.get("ID"));
                if (file.isDirectory()) {
                    files.add(file);
                }
            }
        }
        files.add(LuceneFace.inctance()
                .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_KNOW")));
        files.add(LuceneFace.inctance()
                .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_SITE")));
        files.add(LuceneFace.inctance()
                .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_FILE")));
        DocQueryInter query = DocQueryImpl.getInstance(files);
        String iql = null;
        word = HtmlUtils.HtmlRemoveTag(word.trim());
        if (word.indexOf("TYPE:") >= 0 && iql == null) {
            word = word.substring(word.indexOf("TYPE:") + 5).replaceAll(":", "");
            iql = "WHERE(TYPENAME=" + word + ")";
        }
        if (word.indexOf("TAG:") >= 0 && iql == null) {
            word = word.substring(word.indexOf("TYPE:") + 5).replaceAll(":", "");
            iql = "WHERE(TAGKEY=" + word + ")";
        }
        if (word.indexOf("AUTHOR:") >= 0 && iql == null) {
            word = word.substring(word.indexOf("AUTHOR:") + 7).replaceAll(":", "");
            iql = "WHERE(AUTHOR=" + word + ")";
        }
        if (word.indexOf("TITLE:") >= 0 && iql == null) {
            word = word.substring(word.indexOf("TITLE:") + 6).replaceAll(":", "");
            iql = "WHERE(TITLE=" + word + ")";
        }
        if (iql == null) {
            // word.substring(word.indexOf("TYPE:"));
            iql = "WHERE(TITLE,TEXT,TAGKEY,TYPENAME,AUTHOR=" + word.replaceAll(":", "") + ")";
        }
        if (pagenum == null) {
            pagenum = 1;
        }
        WebHotCase.putCase(word);
        DataResult result = query.queryByMultiIndex(iql, pagenum, 10).getDataResult();
        for (Map<String, Object> node : result.getResultList()) {
            String tags = node.get("TAGKEY").toString();
            String text = node.get("TEXT").toString();
            node.put("DOCDESCRIBE", text.length() > 256 ? text.substring(0, 256) : text);
            if (tags != null && tags.trim().length() > 0) {
                String[] tags1 = tags.trim().replaceAll("，", ",").replaceAll("、", ",").split(",");
                node.put("TAGKEY", Arrays.asList(tags1));
            } else {
                node.put("TAGKEY", new ArrayList<String>());
            }
        }
        return result;
    }

    /**
     * 添加索引
     *
     * @param entity
     */
    @Override
    @Transactional
    public void addLuceneIndex(DocEntire entity) {
        // 做索引
        {
            com.wallellen.lucene.server.DocIndexInter typeindex = null;
            com.wallellen.lucene.server.DocIndexInter groupindex = null;
            try {
                LuceneFace luceneImpl = LuceneFace.inctance();
                if (entity.getDoc().getDomtype().equals("1")) {
                    typeindex = luceneImpl.getDocIndex(luceneImpl
                            .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_KNOW")));
                }
                if (entity.getDoc().getDomtype().equals("3")) {
                    typeindex = luceneImpl.getDocIndex(luceneImpl
                            .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_SITE")));
                }
                if (entity.getDoc().getDomtype().equals("5")) {
                    typeindex = luceneImpl.getDocIndex(luceneImpl
                            .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_FILE")));
                }
                if (farmDocOperate.isAllUserRead(entity.getDoc(), entity.getType())) {
                    if ("1".equals(entity.getDoc().getState())) {
                        if ("1".equals(entity.getDoc().getReadpop())) {
                            // 公开权限索引
                            if (typeindex != null) {
                                typeindex.indexDoc(LuceneDocUtil.getDocMap(entity));
                            }
                        }
                    }
                }
                if (entity.getGroup() != null && !entity.getGroup().getId().isEmpty()) {
                    // 创建小组索引
                    groupindex = luceneImpl
                            .getDocIndex(luceneImpl.getIndexPathFile("GROUP" + entity.getGroup().getId()));
                    groupindex.indexDoc(LuceneDocUtil.getDocMap(entity));

                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                try {
                    if (groupindex != null) {
                        groupindex.close();
                    }
                    if (typeindex != null) {
                        typeindex.close();
                    }
                } catch (Exception e1) {
                    log.error("lucene error:" + e1);
                }
            }
        }

    }

    @Override
    @Transactional
    public void delLuceneIndex(DocEntire doc) {
        // 做索引
        {
            com.wallellen.lucene.server.DocIndexInter index = null;
            com.wallellen.lucene.server.DocIndexInter groupindex = null;
            try {
                LuceneFace luceneImpl = LuceneFace.inctance();
                if (doc.getDoc().getDomtype().equals("1")) {
                    index = luceneImpl.getDocIndex(luceneImpl
                            .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_KNOW")));
                }
                if (doc.getDoc().getDomtype().equals("3")) {
                    index = luceneImpl.getDocIndex(luceneImpl
                            .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_SITE")));
                }
                if (doc.getDoc().getDomtype().equals("5")) {
                    index = luceneImpl.getDocIndex(luceneImpl
                            .getIndexPathFile(ParamService.getInstance().getParameter("LUCENE_DIR_FILE")));
                }
                if (index != null) {
                    index.deleteFhysicsIndex(doc.getDoc().getId());
                }
                if (doc.getDoc().getDocgroupid() != null && !doc.getDoc().getDocgroupid().isEmpty()) {
                    // 删除
                    groupindex = luceneImpl
                            .getDocIndex(luceneImpl.getIndexPathFile("GROUP" + doc.getDoc().getDocgroupid()));
                    groupindex.deleteFhysicsIndex(doc.getDoc().getDocgroupid());
                }
            } catch (Exception e) {
                throw new RuntimeException(e + "删除索引");
            } finally {
                try {
                    if (groupindex != null) {
                        groupindex.close();
                    }
                    if (index != null) {
                        index.close();
                    }
                } catch (Exception e1) {
                    log.error("lucene error:" + e1);
                }
            }
        }
    }

    /**
     * 重做索引
     *
     * @param entity
     */
    @Override
    @Transactional
    public void reLuceneIndex(DocEntire olddoc, DocEntire newdoc) {
        delLuceneIndex(olddoc);
        addLuceneIndex(newdoc);
    }
}
